//
//  NSDate+LYAdd.m
//  LYDevelopKit
//
//  Created by 李阳 on 2018/5/26.
//

#import "NSDate+LYAdd.h"
#import "LYNSMacro.h"

LYSYNTH_DUMMY_CLASS(NSDate_LYAdd)

@implementation NSDate (LYAdd)

+ (NSDateFormatter *)formatter
{
    static NSDateFormatter *fmt;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        fmt = [[NSDateFormatter alloc]init];
    });
    return fmt;
}

+ (NSDate *)dateWithComponents:(void (^)(NSDateComponents *cmp))maker
{
    NSCalendarUnit units = NSCalendarUnitWeekday | NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
    NSDateComponents *cmp = [calendar components:units fromDate:[NSDate date]];
    !maker ?: maker(cmp);
    return [calendar dateFromComponents:cmp];
}

- (BOOL)isEarlierThan:(NSDate *)date usingFormatString:(NSString *)fmtString
{
    NSDate *dateSelf = [self _dateWithFormatString:fmtString];
    NSDate *compareDate = [date _dateWithFormatString:fmtString];
    return [dateSelf compare:compareDate] < 0;
}
- (BOOL)isLaterThan:(NSDate *)date usingFormatString:(NSString *)fmtString
{
    NSDate *dateSelf = [self _dateWithFormatString:fmtString];
    NSDate *compareDate = [date _dateWithFormatString:fmtString];
    return [dateSelf compare:compareDate] > 0;
}

- (NSDate *)_dateWithFormatString:(NSString *)fmtString
{
    if (!fmtString.length)
    {
        return self;
    }
    NSDateFormatter *fmt = [NSDate formatter];
    fmt.dateFormat = fmtString;
    NSString *dateString = [fmt stringFromDate:self];
    if (!dateString.length)
    {
        return self;
    }
    return [fmt dateFromString:dateString];
}

- (dispatch_time_t)wallTime
{
    double seconds = 0;
    double frac = modf(self.timeIntervalSince1970, &seconds);
    
    struct timespec walltime = {
        .tv_sec = (time_t)fmin(fmax(seconds, LONG_MIN), LONG_MAX),
        .tv_nsec = (long)fmin(fmax(frac * NSEC_PER_SEC, LONG_MIN), LONG_MAX)
    };
    
    return dispatch_walltime(&walltime, 0);
}

@end
